﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using ERF;
using FirstPerson.Objects;
using FirstPerson.States;
using FirstPerson.Gametypes;

namespace FirstPerson {
    /// <summary>
    /// The HUD class representing all that is shown in the hud.
    /// </summary>
    public class Hud : DrawableGameComponent {
        private Texture2D hudCrosshair, hud;
        private SpriteFont hudFont;
        private SpriteFont messageFont;
        private double messageTimer = 0;
        private int messageShowTime = 5;
        protected ScoreBoard scoreBoard;

        private SpriteBatch spriteBatch;
        private bool roundStart = true;
        
        private SpriteFont startTimeFont;
        private Vector2 fontPos;

        private TimeSpan countdownTimer = new TimeSpan();
        private int fontScale = 100;
        private int countdownScaleDecrement = 5;
        private double countdownScaleDelay = .035;
        private string countdownString = "";

        /// <summary>
        /// Adds the hud as a service, makes a scoreboard and adds it as a component.
        /// </summary>
        /// <param name="game"></param>
        public Hud(ERFGame game) : base(game) 
        {
            //Game.Services.AddService(typeof(Hud), this);
            this.scoreBoard = new ScoreBoard(game);
            game.Components.Add(this.scoreBoard);
        }

        public SpriteBatch SpriteBatch {
            get { return spriteBatch; }
            set { spriteBatch = value; }
        }

        public void ShowScores(bool show) {
            this.scoreBoard.Visible = show;
        }

        protected override void LoadContent() {
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);

            hudCrosshair = Game.Content.Load<Texture2D>(@"Textures\hudCrosshair");
            hudFont = Game.Content.Load<SpriteFont>(@"Fonts2\FontHud");
            messageFont = Game.Content.Load<SpriteFont>(@"Fonts2\MessageFont");
            hud = Game.Content.Load<Texture2D>(@"Textures\hud");

            startTimeFont = Game.Content.Load<SpriteFont>(@"Fonts2\FontHud");         
            fontPos = new Vector2(Game.GraphicsDevice.Viewport.Width / 2,
                Game.GraphicsDevice.Viewport.Height / 2);

            base.LoadContent();
        }

        public override void Draw(GameTime gameTime) {
            Player player = ((FirstPerson.PlayerHandler)((ERFGame)this.Game).PlayerHandler).HumanPlayer;

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState);

            spriteBatch.Draw(hudCrosshair, new Vector2(Game.GraphicsDevice.Viewport.Width / 2 - (hudCrosshair.Width / 2), Game.GraphicsDevice.Viewport.Height / 2 - (hudCrosshair.Height / 2)), Color.White);

            drawBox(0, Game.GraphicsDevice.Viewport.Height - 50, player.Hp.ToString(), 2);
            drawBox(Game.GraphicsDevice.Viewport.Width - 128, Game.GraphicsDevice.Viewport.Height - 50, player.Ammo.ToString(), 1);
            drawBox(Game.GraphicsDevice.Viewport.Width - 128, 0, player.Kills.ToString(), 0);

            GameType gameType = PlayingState.GetInstance(((ERFGame)Game).StateMachine).GameType;

            TimeSpan duration = new TimeSpan(0, 0, gameType.DurationTime);

            //displays a counter ticking down to zero.
            //gameTime.TotalRealTime - StartTime
            TimeSpan tm = duration - (gameTime.TotalRealTime - gameType.StartTime);
            string time = (tm.Minutes < 10 ? "0" : "") + tm.Minutes.ToString() + " : ";
            time += (tm.Seconds < 10 ? "0" : "") + tm.Seconds.ToString();

            spriteBatch.DrawString(hudFont, time, new Vector2(Game.GraphicsDevice.Viewport.Width / 2 - hudFont.MeasureString(time).X / 2,
                10), Color.Black);

            DrawMessages();

            // Draw the start countdown
            if (roundStart)
                DrawCountdown(gameTime);
            spriteBatch.End();

            base.Draw(gameTime);
        }
        /// <summary>
        /// This changes what is drawn in the countdown and draws it.
        /// </summary>
        /// <param name="gameTime">The gameTime</param>
        private void DrawCountdown(GameTime gameTime)
        {
            countdownTimer += gameTime.ElapsedGameTime;
            if (countdownTimer < TimeSpan.FromSeconds(2) && countdownTimer > TimeSpan.FromSeconds(1))
            {
                countdownString = "4";
                CountdownScale(gameTime);
            }
            if (countdownTimer < TimeSpan.FromSeconds(3) && countdownTimer > TimeSpan.FromSeconds(2))
            {
                countdownString = "3";
                CountdownScale(gameTime);
            }
            if (countdownTimer < TimeSpan.FromSeconds(4) && countdownTimer > TimeSpan.FromSeconds(3))
            {
                countdownString = "2";
                CountdownScale(gameTime);
            }
            if (countdownTimer < TimeSpan.FromSeconds(5) && countdownTimer > TimeSpan.FromSeconds(4))
            {
                countdownString = "1";
                CountdownScale(gameTime);
            }
            if (countdownTimer < TimeSpan.FromSeconds(8) && countdownTimer > TimeSpan.FromSeconds(5))
            {
                countdownString = "GO GO GO";
                if(fontScale > 8)
                    CountdownScale(gameTime);
            }
            if (countdownTimer > TimeSpan.FromSeconds(8))
            {
                roundStart = false;
            }
            // Find the center of the string
            Vector2 FontOrigin = startTimeFont.MeasureString(countdownString) / 2;
            // Draw the string
            spriteBatch.DrawString(startTimeFont, countdownString, fontPos, Color.Red,
                0, FontOrigin, (float)fontScale, SpriteEffects.None, 0f);

        }
        /// <summary>
        /// Scales the font according to the gameTime.
        /// </summary>
        /// <param name="gameTime">The gameTime</param>
        private void CountdownScale(GameTime gameTime)
        {
            countdownScaleDelay -= gameTime.ElapsedGameTime.TotalSeconds;

            // If the countdownScale delays has dropped below zero, then it is time to 
            // scale the font down a little bit more.
            if (countdownScaleDelay <= 0)
            {
                // Reset the countdownScaleDelay
                countdownScaleDelay = .035;

                fontScale -= countdownScaleDecrement;

                // If the fontScale < = 0 reset it to 100 to be able to scale it 
                // down again for the next number

                if (fontScale <= 0)
                {
                    fontScale = 100;
                }
            }
        }
        /// <summary>
        /// Draw a box at a desired place on the screen with a desired text.
        /// </summary>
        /// <param name="x">The X position where the box is to be drawn</param>
        /// <param name="y">The Y position where the box is to be drawn</param>
        /// <param name="text">The text to be drawn</param>
        /// <param name="index"></param>
        public void drawBox(int x, int y, String text, int index) {

            spriteBatch.Draw(hud, new Rectangle(x, y, 128, 50), new Rectangle(0, index * 100, 256, 100), Color.White);
            Vector2 textSize = hudFont.MeasureString(text);
            spriteBatch.DrawString(hudFont, text, new Vector2(x + 128 * 0.63f - textSize.X / 2, y + 25 - textSize.Y / 2), new Color(1f, 1f, 1f, 0.8f));
        }
        /// <summary>
        /// Draws a message on the screen.
        /// </summary>
        private void DrawMessages() {
            List<String> messages = GameConsole.GetInstance.Messages.ToList<String>();

            for (int i = 0; i < messages.Count; i++)
                spriteBatch.DrawString(messageFont, messages[i], new Vector2(10, 10 + i * 15), Color.WhiteSmoke);
        }

        public override void Update(GameTime gameTime) {
            if (messageTimer == 0)
                messageTimer = gameTime.TotalGameTime.TotalSeconds;

            if (GameConsole.GetInstance.Messages.Count > 0 && gameTime.TotalGameTime.TotalSeconds - messageTimer > messageShowTime) {
                GameConsole.GetInstance.Messages.Dequeue();

                messageTimer = gameTime.TotalGameTime.TotalSeconds;
            }

            base.Update(gameTime);
        }

        public void ActivateHud() {
            this.Visible = true;
        }

        public void DeactivateHud() {
            this.Visible = false;
        }
    }
}
